/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.klikmee.sms.core.model;

import java.io.Serializable;
import java.text.MessageFormat;
import java.util.Date;
import java.util.Set;

import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

/**
 * 
 * @author makcro
 */
@Entity
@Table(name = "outgoingmessage")
@NamedQueries({
		@NamedQuery(name = "OutgoingMessage.findAll", query = "SELECT o FROM OutgoingMessage o"),
		@NamedQuery(name = "OutgoingMessage.findById", query = "SELECT o FROM OutgoingMessage o WHERE o.id = :id"),
		@NamedQuery(name = "OutgoingMessage.findByFromNumber", query = "SELECT o FROM OutgoingMessage o WHERE o.fromNumber = :fromNumber"),
		@NamedQuery(name = "OutgoingMessage.findByToNumber", query = "SELECT o FROM OutgoingMessage o WHERE o.toNumber = :toNumber"),
		@NamedQuery(name = "OutgoingMessage.findByMessage", query = "SELECT o FROM OutgoingMessage o WHERE o.message = :message"),
		@NamedQuery(name = "OutgoingMessage.findByProvidersMesssageId", query = "SELECT o FROM OutgoingMessage o WHERE o.providersMesssageId = :providersMesssageId"),
		@NamedQuery(name = "OutgoingMessage.findByState", query = "SELECT o FROM OutgoingMessage o WHERE o.state = :state"),
		@NamedQuery(name = "OutgoingMessage.findByStateChangeTime", query = "SELECT o FROM OutgoingMessage o WHERE o.stateChangeTime = :stateChangeTime"),
		@NamedQuery(name = "OutgoingMessage.findByOurOutGoingTime", query = "SELECT o FROM OutgoingMessage o WHERE o.ourOutGoingTime = :ourOutGoingTime"),
		@NamedQuery(name = "OutgoingMessage.findByTypeOfMessage", query = "SELECT o FROM OutgoingMessage o WHERE o.typeOfMessage = :typeOfMessage"),
		@NamedQuery(name = "OutgoingMessage.findByDataCoding", query = "SELECT o FROM OutgoingMessage o WHERE o.dataCoding = :dataCoding"),
		@NamedQuery(name = "OutgoingMessage.findByDeliveryStatus", query = "SELECT o FROM OutgoingMessage o WHERE o.deliveryStatus = :deliveryStatus"),
		@NamedQuery(name = "OutgoingMessage.findByDeliveryStatusChangeTime", query = "SELECT o FROM OutgoingMessage o WHERE o.deliveryStatusChangeTime = :deliveryStatusChangeTime"),
		@NamedQuery(name = "OutgoingMessage.findByMessageBody", query = "SELECT o FROM OutgoingMessage o WHERE o.messageBody = :messageBody"),
		@NamedQuery(name = "OutgoingMessage.findByUrl", query = "SELECT o FROM OutgoingMessage o WHERE o.url = :url"),
		@NamedQuery(name = "OutgoingMessage.findNumberOfOutgoingMessageByProviderAndProvidersMessageID", query = "SELECT COUNT(om) from OutgoingMessage om WHERE "
				+ "(om.providersMesssageId  LIKE (:providersMesssageId) OR om.providersMesssageId  LIKE (:providersMesssageId2)) " + " AND om.provider = :provider"),
		@NamedQuery(name = "OutgoingMessage.findByProvidersMessageIdAndProviderName", query = "SELECT om FROM OutgoingMessage om WHERE om.providersMesssageId = :providersMesssageId "
				+ "AND om.provider.name = :providerName "),
		@NamedQuery(name = "OutgoingMessage.findByMessageIdAndProvider", query = "SELECT om FROM OutgoingMessage om WHERE om.id = :id AND om.provider.name = :providerName "),
		@NamedQuery(name = "OutgoingMessage.findMessagesForSending", query = "SELECT om from OutgoingMessage as om WHERE " + "om.state = :createdState " + "OR ( om.state = :waitingToBeSentState "
				+ "OR  om.state = :paymentMessagesWaitingToBeSentState )"),
		@NamedQuery(name = "OutgoingMessage.findDeliveredByService", query = "SELECT om from OutgoingMessage as om WHERE " + "(om.state = :deliveredAndCharged "
				+ "OR om.state = :notDeliveredNotCharged " + "OR om.state = :deliveryState) " + "AND om.service = :service"),
		@NamedQuery(name = "OutgoingMessage.findDeliveredByServiceAndTime", query = "SELECT om from OutgoingMessage om WHERE " + "(om.state = :deliveredAndChargedState OR "
				+ "om.state = :notDeliveredAndNotChargedState OR " + "om.state = :deliveryState OR " + "om.state = :deliveredAndChargedStateServiceNotified OR "
				+ "om.state = :notDeliveredAndNotChargedStateServiceNotified OR " + "om.state = :deliveryStateServiceNotified ) AND " + "om.service = :service AND "
				+ "om.deliveryStatusChangeTime >= :time"),
		@NamedQuery(name = "OutgoingMessage.findByProvidersMessageIdAndProvider", query = "SELECT om FROM OutgoingMessage om WHERE om.providersMesssageId = :providersMesssageId "
				+ "AND om.provider = :provider"),
		@NamedQuery(name = "OutgoingMessage.findByMessageIdAndProvider", query = "SELECT om FROM OutgoingMessage om WHERE om.id = :messsageId "
				+ "AND om.provider = :provider") })
public class OutgoingMessage implements Serializable {

	private static final long	serialVersionUID	= 1L;
	@Id
	@GeneratedValue(generator = "OutgoingIdGenerator", strategy = GenerationType.TABLE)
	@Basic(optional = false)
	@Column(name = "Id", nullable = false)
	private Long				id;
	@Column(name = "FromNumber", length = 100)
	private String				fromNumber;
	@Column(name = "ToNumber", length = 100)
	private String				toNumber;
	@Column(name = "MtsSessionId", length = 128)
	private String				mtsSessionId;
	@Column(name = "Message", length = 1000)
	private String				message;
	@Column(name = "ProvidersMesssageId", length = 100)
	private String				providersMesssageId;
	@Column(name = "State")
	private Integer				state;
	@Column(name = "StateChangeTime")
	@Temporal(TemporalType.TIMESTAMP)
	private Date				stateChangeTime;
	@Column(name = "OurOutGoingTime")
	@Temporal(TemporalType.TIMESTAMP)
	private Date				ourOutGoingTime;
	@Column(name = "TypeOfMessage")
	private Integer				typeOfMessage;
	@Column(name = "DataCoding", length = 10)
	private String				dataCoding;
	@Column(name = "DeliveryStatus")
	private Integer				deliveryStatus;
	@Column(name = "DeliveryStatusChangeTime")
	@Temporal(TemporalType.TIMESTAMP)
	private Date				deliveryStatusChangeTime;
	@Column(name = "MessageBody", length = 1000)
	private String				messageBody;
	@Column(name = "Url", length = 1000)
	private String				url;
	@Lob
	@Column(name = "Data")
	private byte[]				data;
	@JoinColumn(name = "Provider", referencedColumnName = "id")
	@ManyToOne
	private Provider			provider;
	@JoinColumn(name = "Service", referencedColumnName = "Id")
	@ManyToOne
	private Service				service;
	@OneToMany(mappedBy = "outgoingMessage", cascade = CascadeType.PERSIST, fetch = FetchType.EAGER)
	private Set<PaymentInvoice>	paymentInvoiceList;

	public OutgoingMessage() {
	}

	public OutgoingMessage(Long id) {
		this.id = id;
	}

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getFromNumber() {
		return fromNumber;
	}

	public void setFromNumber(String fromNumber) {
		this.fromNumber = fromNumber;
	}

	public String getToNumber() {
		return toNumber;
	}

	public void setToNumber(String toNumber) {
		this.toNumber = toNumber;
	}

	public String getMessage() {
		return message;
	}

	public void setMessage(String message) {
		this.message = message;
	}

	public String getProvidersMesssageId() {
		return providersMesssageId;
	}

	public void setProvidersMesssageId(String providersMesssageId) {
		this.providersMesssageId = providersMesssageId;
	}

	public Integer getState() {
		return state;
	}

	public void setState(Integer state) {
		this.state = state;
		this.stateChangeTime = new Date();
	}

	public Date getStateChangeTime() {
		return stateChangeTime;
	}

	public void setStateChangeTime(Date stateChangeTime) {
		this.stateChangeTime = stateChangeTime;
	}

	public Date getOurOutGoingTime() {
		return ourOutGoingTime;
	}

	public void setOurOutGoingTime(Date ourOutGoingTime) {
		this.ourOutGoingTime = ourOutGoingTime;
	}

	public Integer getTypeOfMessage() {
		return typeOfMessage;
	}

	public void setTypeOfMessage(Integer typeOfMessage) {
		this.typeOfMessage = typeOfMessage;
	}

	public String getDataCoding() {
		return dataCoding;
	}

	public void setDataCoding(String dataCoding) {
		this.dataCoding = dataCoding;
	}

	public Integer getDeliveryStatus() {
		return deliveryStatus;
	}

	public void setDeliveryStatus(Integer deliveryStatus) {
		this.deliveryStatus = deliveryStatus;
		this.deliveryStatusChangeTime = new Date();
	}

	public Date getDeliveryStatusChangeTime() {
		return deliveryStatusChangeTime;
	}

	public void setDeliveryStatusChangeTime(Date deliveryStatusChangeTime) {
		this.deliveryStatusChangeTime = deliveryStatusChangeTime;
	}

	public String getMessageBody() {
		return messageBody;
	}

	public void setMessageBody(String messageBody) {
		this.messageBody = messageBody;
	}

	public String getUrl() {
		return url;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public byte[] getData() {
		return data;
	}

	public void setData(byte[] data) {
		this.data = data;
	}

	public Provider getProvider() {
		return provider;
	}

	public void setProvider(Provider provider) {
		this.provider = provider;
	}

	public Service getService() {
		return service;
	}

	public void setService(Service service) {
		this.service = service;
	}

	public Set<PaymentInvoice> getPaymentInvoiceList() {
		return paymentInvoiceList;
	}

	public void setPaymentInvoiceList(Set<PaymentInvoice> paymentInvoiceList) {
		this.paymentInvoiceList = paymentInvoiceList;
	}

	public String getMtsSessionId() {
		return mtsSessionId;
	}

	public void setMtsSessionId(String mtsSessionId) {
		this.mtsSessionId = mtsSessionId;
	}

	@Override
	public int hashCode() {
		int hash = 0;
		hash += (id != null ? id.hashCode() : 0);
		return hash;
	}

	@Override
	public boolean equals(Object object) {
		if (!(object instanceof OutgoingMessage)) {
			return false;
		}
		OutgoingMessage other = (OutgoingMessage) object;
		if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
			return false;
		}
		return true;
	}

	@Override
	public String toString() {
		return MessageFormat.format( "OutgoingMessage[{0}]", this.id);
	}

	public static OutgoingMessage createFrom(IncomingMessage incomingMessage) {
		OutgoingMessage instance = new OutgoingMessage();
		instance.setData(incomingMessage.getData());
		instance.setDataCoding(incomingMessage.getDataCoding());
		instance.setDeliveryStatus(null);
		instance.setDeliveryStatusChangeTime(null);
		instance.setFromNumber(incomingMessage.getToNumber());
		instance.setId(null);
		instance.setMessage(null);
		instance.setMessageBody(null);
		instance.setOurOutGoingTime(null);
		instance.setPaymentInvoiceList(null);
		instance.setProvider(incomingMessage.getProvider());
		instance.setProvidersMesssageId(incomingMessage.getProviderMessageId());
		//instance.setService(incomingMessage.getService());
		instance.setState(null);
		instance.setStateChangeTime(null);
		instance.setToNumber(incomingMessage.getFromNumber());
		instance.setTypeOfMessage(null);
		instance.setUrl(null);
		instance.setMtsSessionId(incomingMessage.getMtsSessionId());
		return instance;
	}
}
